home *** CD-ROM | disk | FTP | other *** search
- # SpecTcl, by S. A. Uhler
- # Copyright (c) 1994-1995 Sun Microsystems, Inc.
- #
- # See the file "license.txt" for information on usage and redistribution
- # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- #
- # compile a ui file into tk code - TAKE 2
- # Thu Apr 6 14:22:59 PDT 1995
-
- # Each project file has the following format:
- # 1: title-> WidGet file, created: <date>
-
- # 2: widget_data ...
- #
- # widget data consists of:
- # Widget <name>
- # <tab> <type> <name> <value>
- # ...
-
- # pick up data filters
-
- if {[info procs install_filters] == ""} {
- source filters.tk
- install_filters
- }
-
- # format string for running "hook" code [not used anymore]
-
- set Format {
- if {[info commands %s] != {}} {
- eval {%s $root} $args
- }
- }
-
- # compile a ui into a tk program
- # file: the unix file containing the ui description
- # out: The file to write the tk program to (defaults to stdout)
- # prefix: The procedure prefix
- # run: Invoke the generated procedure (not used)
-
- proc compile {file {out ""} {prefix ""} {run ""}} {
- global Widget_data Format Masters Version
- set Id "WidGet file"
- catch "unset Masters"
- array set map {row height column width}
-
- if {![file readable $file]} {
- puts stderr "$file does not exist"
- return 1
- }
- set fd [open $file r]
-
- set line ""
- gets $fd line
- if {[string first $Id $line] != 0} {
- puts stderr "$file is not a UI file"
- close $fd
- return 1
- }
-
- if {$out == ""} {
- set out_fd stdout
- } else {
- if {[file exists $out] && ![file writable $out]} {
- set _Message "cant write to $out"
- return 1
- }
- set out_fd [open $out w]
- }
-
-
- # gather up all of the data for each widget
-
- while {1} {
- gets $fd line
- if {[eof $fd]} break
-
- # gather entire line
-
- while {![info complete $line]} {
- append line "\n[gets $fd]"
- # puts stderr gulp
- }
- if {[string first Widget $line] == 0} {
- set name [lindex $line 1]
- lappend names $name
- upvar #0 __X_$name data
- } else {
- set index -1
- foreach i {type option value} {
- set $i [lindex $line [incr index]]
- }
-
- # fix the font name
-
- if {$option == "font"} {
- # puts stderr "Filtering font"
- $Widget_data(outfilter:font) dummy font value
- }
-
- if {$option == "master"} {
- set Masters([string trimleft [expr {$value=="" ? "f" : $value}] .]) 1
- }
- set data($type,$option) $value
- }
- }
- close $fd
-
- # now output the info as a tcl script
-
- if {$prefix == ""} {
- set prefix [file root [file tail $file]]
- }
- puts $out_fd "# interface generated by SpecTcl version $Version from $file"
- puts $out_fd "# root is the parent window for this user interface"
- puts $out_fd "\nproc ${prefix}_ui {root args} {"
- puts $out_fd {
- # this treats "." as a special case
-
- if {$root == "."} {
- set base ""
- } else {
- set base $root
- }
- }
-
- # run any prefix code (Turn off for now)
- # puts $out_fd [format $Format ${prefix}_prefix ${prefix}_prefix]
-
- # now create the widgets (and the tags)
- # Sort the widgets to end up with the correct tabbing order
-
- set names [lsort -command "frames_first" $names]
- foreach name $names {
- upvar #0 __X_$name data
-
- if {$name == "f" } continue
-
- # gather up the widget command.
- # Substitute %W's in -command. This needs to change
-
- puts -nonewline $out_fd "\t$data(other,type) \$base.$data(other,item_name)"
- set options [lsort [array names data configure,*]]
- set font ""
- foreach option $options {
- regsub configure, $option {} param
- set value $data($option)
- set check [expr [string match *command* $param] || [string match *variable* $param]]
- if {$check && [string match {*%[BWMR]*} $value]} {
- regsub -all {([][$])} $value {\\\1} value ;# quote variables and []'s
- regsub -all {(^|[^%])%W} $value \\1\$base.$data(other,item_name) value
- regsub -all {(^|[^%])%B} $value \\1\$base value
- regsub -all {(^|[^%])%R} $value \\1\$root value
- regsub -all {(^|[^%])%M} $value \\1[real_master $name] value
- regsub -all {([^\\])?"} $value {\1\\"} value
- puts -nonewline $out_fd " \\\n\t\t-$param \"$value\""
- } else {
-
- # To prevent bad fonts from aborting the entire ui,
- # don't issue -font commands directly, but use "configure"
- # surrounded by a catch instead
-
- set stuff "-$param [list $value]"
- if {$param == "font"} {
- append font $stuff
- } else {
- puts -nonewline $out_fd " \\\n\t\t$stuff"
- }
- }
- }
-
- # now issue the font configure command in a catch
-
- if {$font != ""} {
- puts -nonewline $out_fd \
- "\n\tcatch \{\n\t\t\$base.$data(other,item_name) configure \\\n\t\t\t$font\n\t\}"
- }
- puts $out_fd "\n"
-
- # find the tags
-
- if {$data(other,tags) != ""} {
- append tags "\tbindtags \$base.$data(other,item_name) [list $data(other,tags)]\n"
- }
-
- }
-
- # print out any binding tags
-
- if {[info exists tags]} {
- puts $out_fd "\n\t# binding tags\n\n$tags"
- }
-
- # now create the geometry management commands
- # this has to wait until all of the widgets are created to
- # avoid forward references
-
- puts $out_fd "\n\t# Geometry management"
- foreach name $names {
- upvar #0 __X_$name data
- if {[set master [real_master $name]] == ""} {
- continue
- }
- puts $out_fd ""
- puts -nonewline $out_fd "\tblt_table $master \$base.$data(other,item_name) "
- puts -nonewline $out_fd "\t$data(geometry,row),$data(geometry,column) "
- foreach option [lsort [array names data geometry,*]] {
- regsub geometry, $option {} param
- if {$param == "row" || $param == "column"} continue
- puts -nonewline $out_fd " \\\n\t\t-$param [list $data($option)]"
- }
- }
-
- # now for the resize behavior, this is only run for geometry masters"
-
- puts $out_fd "\n\n\t# Resize behavior management"
-
- foreach name [array names Masters] {
- upvar #0 __X_$name data
- # puts "Processing master $name"
- if {$data(other,item_name) == "f"} {
- set master \$root
- } else {
- set master \$base.$data(other,item_name)
- }
- puts $out_fd ""
- # puts "widget:$name master:$master"
- # parray data
- foreach dim {row column} {
- puts $out_fd "\tblt_table $dim $master configure all -resize none"
- set list [get_resize $data(other,resize_$dim)]
- if {[llength $list] > 0} {
- puts $out_fd "\tblt_table $dim $master configure [list $list] -resize both"
- }
- set index 0
- foreach size $data(other,min_$dim) {
- puts $out_fd "\tblt_table $dim $master configure [incr index] -$map($dim) \{$size Inf\}"
- }
- }
- }
-
- # now output the additional interface code (turned off for now)
- # puts $out_fd [format $Format ${prefix}_postfix ${prefix}_postfix]
-
- global __X_f
- puts $out_fd "# additional interface code"
- if {[info exists __X_f(other,code)]} {
- puts $out_fd $__X_f(other,code)
- }
- puts $out_fd "# end additional interface code\n"
-
- puts $out_fd "}"
-
- if {$run != ""} {
- puts $out_fd "catch { source [file root [file tail $file]].tcl}"
- if {$run != "."} {
- puts $out_fd "wm withdraw .;toplevel $run;wm title $run [file tail $file]"
- }
- puts $out_fd "[file tail $file]_ui $run ;# run the interface in ."
- }
-
- if {$out_fd != "stdout"} {
- close $out_fd
- # puts "Closing $out_fd"
- }
- foreach i [info globals __X_*] {
- global $i
- unset $i
- }
- }
-
- # figure out the resize behavior
-
- proc get_resize {list} {
- set index 0
- set result ""
- foreach i $list {
- if {[lindex "x $list" [incr index]] > 1} {
- lappend result $index
- }
- }
- return $result
- }
-
- # Sort the widgets to generate the proper stacking order
- # * Create all the frames first. Make sure all outer frames are
- # created before the inner ones
- # * Create all widgets in the specified tabbing order. If the tab order is the
- # same, then use row/col order based on the coordinates of the containing
- # table cell
-
- # This version depends upon the running state of SpecTcl, and needs to be
- # re-written to permit the compiler to be invoked as a separate app
-
- proc frames_first {name1 name2} {
- upvar #0 __X_$name1 data1 __X_$name2 data2
- dputs "compare $name1 $name2"
-
- # both frames
- if {$data1(other,type) == "frame" && $data2(other,type) == "frame"} {
- dputs " frames: $data2(other,level) - $data1(other,level)"
- return [expr $data1(other,level) - $data2(other,level)]
- }
-
- # 1 frame, 1 widget
- if {$data1(other,type) == "frame"} {
- return -1
- } elseif {$data2(other,type) == "frame"} {
- return 1
- }
-
- # sort by explicit tabbing order field
- if {[set result [string compare $data1(other,tabbing) $data2(other,tabbing)]] != 0} {
- dputs " order $result"
- return $result
- }
-
- # compute order based on cell coords
-
- set c1 [get_tabbing_coords .can.f.$name1]
- set c2 [get_tabbing_coords .can.f.$name2]
-
- foreach index {0 1} {
- set diff [expr [lindex $c1 $index] - [lindex $c2 $index]]
- dputs " diff ($index) -> $diff"
- if {$diff != 0} {return $diff}
- }
- dputs " equal??"
- return 0
- }
-
-
- # find the real master of this window, as the user may have changed its name.
-
- proc real_master {name} {
- upvar #0 __X_$name data
- set master [string trimleft $data(other,master) .]
- dputs $master
-
- if {$name == "f" } return ""
-
- if {$master == ""} {
- return {$root}
- } else {
- # the name of the master may have been changed!
- upvar #0 __X_$master m
- set master $m(other,item_name)
- return \$base.$master
- }
- }
-